'use strict';
require('log-timestamp');
const debug = true;
const faker = require('faker');
const model = require('../models/models');
const User = model.user;
const Comment = model.comment;
const Moment = model.momentResource;
const Video = model.videoResource;
const jwt = require('jsonwebtoken');
const config = require('../config');
const assert = require('assert');
const count = 3;

var phoneFormalize = (phoneNum) => {
  return phoneNum.replace(/ /g, '')
}

function objCopy(sourceObj, destObj) {
  for(let k in sourceObj) {
    destObj[k] = sourceObj[k];
  }
}

/**
 * validate the mobile
 * @param {*} countryCode
 * @param {*} mobile
 */
function mobileValidate(countryCode, mobile) {
  if(!countryCode || !mobile) return false;
  var retval = true;
  try {
    switch(Number(countryCode)) {
      case 65:
        //validate S'poer mobile phone#
        if(!countryCode || !mobile) retval = false;
        break;
      case 86:
        //validate China's mobile phone#        
        break;
      default:
        break;
    }

  } catch(error) {

  }
  return retval
}

function getToken(seed) {
  return jwt.sign({
    seed: seed,
  }, config.secret, {});
}

function mockupVideo() {
  var r = new Video({
    resourceId: 'mockup' + faker.random.uuid(),
    category: faker.lorem.word(),
    userName: faker.name.findName(),
    userCode: faker.random.uuid(),
    uploadTime: faker.random.number(),
    likeCount: faker.random.number(),
    likes: [faker.random.uuid(), faker.random.uuid(), faker.random.uuid()],
    resourceUri: faker.internet.url(),
    preview: faker.image.imageUrl(),
    commentCount: faker.random.number(),
    followingCount: faker.random.number(),
    favouriteCount: faker.random.number(),
    shareCount: faker.random.number(),
    favouritedBy: [faker.random.uuid(), faker.random.uuid(), faker.random.uuid()],
    sharedBy: [faker.random.uuid(), faker.random.uuid(), faker.random.uuid()],
    shares: [''],
    resourceType: 'video',
    comments: [faker.random.uuid(), faker.random.uuid(), faker.random.uuid()],
    // tags: [{ name: faker.name.firstName(), code: faker.random.number() }],
    music: {
      musicid: faker.random.uuid(),
      start: 0,
      end: faker.random.number(),
    },
    fileSize: faker.random.number() + 'kb',
    content: faker.lorem.sentences(),
    title: faker.lorem.sentences(),
    description: faker.lorem.sentences(),
    lat: faker.address.latitude(),
    lon: faker.address.longitude(),
    permission: 'public'
  });
  var p0 = r.save();
  assert.ok(p0 instanceof Promise);
  p0.catch(err => {
    console.log(err)
  });
}

function mockupMoment() {
  var r = new Moment({
    // category: faker.lorem.word(),
    type: 'text',
    resourceId: faker.random.uuid(),
    resourceStatus: true,
    // uploadUser: 'e2aac8be-1c48-42b4-ac13-7e68f87d0a81',
    // userCode: faker.random.uuid(),
    uploadTime: faker.random.number(),
    likeCount: faker.random.number(),
    favouriteCount: faker.random.number(),
    resourceType: 'moment',
    tags: [{name: faker.name.firstName(), code: faker.random.number()}],
    lat: faker.address.latitude(),
    lon: faker.address.longitude(),
    permission: 'public',
    userCode: faker.random.uuid(),
    userName: faker.name.firstName(),
    shares: {
      count: faker.random.number(),
      userCode: [faker.random.uuid()]
    },
    photoArray: [
      {
        origin: faker.image.imageUrl(),
        uploadTime: faker.date.recent(),
        medium: faker.image.imageUrl(),
        small: faker.image.imageUrl()
      },
      {
        origin: faker.image.imageUrl(),
        uploadTime: faker.date.recent(),
        medium: faker.image.imageUrl(),
        small: faker.image.imageUrl()
      },
      {
        origin: faker.image.imageUrl(),
        uploadTime: faker.date.recent(),
        medium: faker.image.imageUrl(),
        small: faker.image.imageUrl()
      }
    ]
  });
  var p0 = r.save();
  assert.ok(p0 instanceof Promise);
  p0.then(function(doc) {
    assert.equal(doc.resourceId, "a12345");
  }).catch(err => {
  });
}

function mockupUserMoment(userCode) {
  var r = new Moment({
    // category: faker.lorem.word(),
    type: 'text',
    resourceId: faker.random.uuid(),
    resourceStatus: true,
    uploadTime: faker.random.number(),
    likeCount: faker.random.number(),
    favouriteCount: faker.random.number(),
    resourceType: 'moment',
    body: faker.lorem.paragraph(),
    tags: [{name: faker.name.firstName(), code: faker.random.number()}],
    lat: faker.address.latitude(),
    lon: faker.address.longitude(),
    permission: 'public',
    userCode: userCode,
    userName: faker.name.firstName(),
    shares: {
      count: faker.random.number(),
      userCode: [faker.random.uuid()]
    },
    photoArray: [
      {
        origin: faker.image.imageUrl(),
        uploadTime: faker.date.recent(),
        medium: faker.image.imageUrl(),
        small: faker.image.imageUrl()
      },
      {
        origin: faker.image.imageUrl(),
        uploadTime: faker.date.recent(),
        medium: faker.image.imageUrl(),
        small: faker.image.imageUrl()
      },
      {
        origin: faker.image.imageUrl(),
        uploadTime: faker.date.recent(),
        medium: faker.image.imageUrl(),
        small: faker.image.imageUrl()
      }
    ]
  });
  var p0 = r.save();
  assert.ok(p0 instanceof Promise);
  p0.then(function(doc) {
    assert.equal(doc.resourceId, "a12345");
  }).catch(err => {
  });
}

function mockupUser() {
  var u = new User({
    following: [faker.random.uuid()],
    follower: [faker.random.uuid()],
    favourites: [faker.random.number()],
    mobile: faker.phone.phoneNumber(),
    countryCode: '65',
    userCode: faker.random.uuid(),
    name: faker.name.findName(),
    nickName: faker.name.findName(),
    gender: randomChoice([1, 0]),
    region: faker.random.locale(),
    level: faker.random.number(),
    language: faker.random.locale(),
    birthday: faker.date.past(),
    facebook: {
      facebookId: faker.random.uuid(),
      expired: faker.random.number(),
      token: faker.random.uuid(),
      picUrl: faker.internet.url(),
    },
    wechat: {
      wechatId: faker.random.uuid(),
      expired: faker.random.number(),
      token: faker.random.uuid(),
      picUrl: faker.internet.url(),
    },
    password: faker.internet.password(),
    token: faker.random.uuid(),
    isEnabled: true,
    accountType: randomChoice(['mobile', 'facebook', 'wechat']),
    interests: [faker.lorem.word()],
    email: faker.internet.email(),
    logintime: faker.date.recent(),
    roleType: 2,
    //roleType: randomChoice(['2', '1', '0']),
    wallet: {id: '1', amount: faker.finance.amount(),},
    resourceType: randomChoice(['broadcast', 'moment', 'video']),
    // publishedResources: []
  });
  u.avatar = {
    origin: faker.image.imageUrl(),
    uploadTime: faker.date.recent(),
    medium: faker.image.imageUrl(),
    small: faker.image.imageUrl()
  };
  let g_get = {
    giftid: faker.random.number(),
    money: faker.finance.amount(),
    transTime: faker.date.recent()
  };
  let g_sent = {
    giftid: faker.random.number(),
    money: faker.finance.amount(),
    transTime: faker.date.recent()
  };
  u.giftsSent = g_sent;
  // u.giftsReceived = g_get;

  // u.save((err)=>{err?console.log("error message::"+err):console.log('user record is successfully saved ')})
  var promise = u.save();
  assert.ok(promise instanceof Promise);
  promise.then(function(doc) {
    assert.equal(doc.resourceId, "a12345");
  }).catch(err => {
  });
}

function getCastResource(userCode) {
  var r = {
    category: faker.lorem.word(),
    resourceId: faker.random.uuid(),
    ChannelId: faker.random.uuid(),
    uploadUser: faker.name.firstName(),
    uploadUserCode: faker.random.uuid(),
    uploadTime: faker.random.number(),
    likeCount: faker.random.number(),
    commentCount: faker.random.number(),
    followingCount: faker.random.number(),
    favouriteCount: faker.random.number(),
    resourceType: 'broadcast',
    tags: [{name: faker.name.firstName(), code: faker.random.number()}],
    title: faker.lorem.word(),
    lat: faker.address.latitude(),
    lon: faker.address.longitude(),
    description: faker.lorem.text(),
    audiences: {
      count: faker.random.number(),
      userCode: [faker.random.uuid()]
    },
    shares: {
      count: faker.random.number(),
      userCode: [faker.random.uuid()]
    },
    height: faker.random.number(),
    width: faker.random.number(),
    length: faker.random.number(),
    chatChannel: {
      channelId: faker.random.uuid(),
      created: faker.random.number(),
      name: faker.random.words()
    },
    ingestChannel: faker.random.toString(),
    coverImage: {
      originImage: faker.image.imageUrl(),
      mediumImage: faker.image.imageUrl(),
      smallImage: faker.image.imageUrl(),
      uploadedTime: faker.random.number(),
    },
    preview: faker.internet.url(),
    resourceUri: faker.internet.url(),
    type: randomChoice(['archived', 'live']),
    action: randomChoice(['add', 'update'])
  };
  var commentIdList = [];

  for(let j = 0; j < count; j++) {
    var c = getComment(r.resourceId, userCode);
    // var c = new Comment();
    // objCopy(c, comment);

    //comment.save();

    commentIdList.push(c.commentId);
    //child comments
    // for (let k = 0; k < 10; k++) {
    //   var childComment = {
    //     body: faker.lorem.sentence(),
    //     postTime: faker.date.recent(),
    //     userCode: userCode
    //   };
    //   comment.childComments.push(childComment)
  }

  //just save the commentId, not whole comment document
  r.comments = commentIdList;

  return r;
}

function getResource(userCode, resourceType) {
  var r = {
    category: faker.lorem.word(),
    resourceId: faker.random.uuid(),
    resourceStatus: faker.random.boolean(),
    ChannelId: faker.random.uuid(),
    uploadUser: faker.name.firstName(),
    uploadUserCode: faker.random.uuid(),
    uploadTime: faker.random.number(),
    likeCount: faker.random.number(),
    commentCount: faker.random.number(),
    followingCount: faker.random.number(),
    favouriteCount: faker.random.number(),
    resourceType: randomChoice(['broadcast', 'moment', 'video']),
    tags: [{name: faker.name.firstName(), code: faker.random.number()}],
    fileSize: faker.random.number(),
    content: faker.lorem.sentence(),
    title: faker.lorem.word(),
    lat: faker.address.latitude(),
    lon: faker.address.longitude(),
    description: faker.lorem.text(),
    permission: randomChoice(['public', 'follower', 'private']),
    audiences: {
      count: faker.random.number(),
      userCode: [faker.random.uuid()]
    },
    shares: {
      count: faker.random.number(),
      userCode: [faker.random.uuid()]
    },
    height: faker.random.number(),
    width: faker.random.number(),
    length: faker.random.number(),
    chatChannel: {
      channelId: faker.random.uuid(),
      created: faker.random.number(),
      name: faker.random.words()
    },
    ingestChannel: faker.random.toString(),
    coverImage: {
      originImage: faker.image.imageUrl(),
      mediumImage: faker.image.imageUrl(),
      smallImage: faker.image.imageUrl(),
      uploadedTime: faker.random.number(),
    },
    preview: faker.internet.url(),
    resourceUri: faker.internet.url(),
    music: {
      musicid: faker.random.uuid,
      start: faker.random.number(),
      end: faker.random.number(),
    },
    photoArray: {
      origin: faker.image.imageUrl(),
      uploadTime: faker.date.recent(),
      medium: faker.image.imageUrl(),
      small: faker.image.imageUrl()
    },
    type: randomChoice(['archived', 'live']),
    action: randomChoice(['add', 'update'])
  };
  var commentIdList = [];

  for(let j = 0; j < count; j++) {
    var c = getComment(r.resourceId, userCode);
    // var c = new Comment();
    // objCopy(c, comment);

    //comment.save();

    commentIdList.push(c.commentId);
    //child comments
    // for (let k = 0; k < 10; k++) {
    //   var childComment = {
    //     body: faker.lorem.sentence(),
    //     postTime: faker.date.recent(),
    //     userCode: userCode
    //   };
    //   comment.childComments.push(childComment)
  }

  //just save the commentId, not whole comment document
  r.comments = commentIdList;

  return r;
}

function getComment(parentId, userCode) {
  var comment = new Comment({
    resourceId: faker.random.uuid(),
    parentId: faker.random.uuid(),
    commentId: faker.random.uuid(),
    body: faker.lorem.sentence(),
    postTime: faker.date.recent(),
    childrenIds: [],
    createdBy: faker.random.uuid(),
    createdByName: faker.name.firstName(),
    replyTo: faker.random.uuid(),
    replyToName: faker.name.firstName(),
  });
  return comment
}

// randomly select one element from array
function randomChoice(arr) {
  return arr[Math.floor(Math.random() * arr.length)];
}

/**
 * 拼接对象为请求字符串
 * @param {Object} obj - 待拼接的对象
 * @returns {string} - 拼接成的请求字符串
 */
function encodeParams(obj) {
  const params = []
  Object.keys(obj).forEach((key) => {
    let value = obj[key]
    // 如果值为undefined我们将其置空
    if(typeof value === 'undefined'){
      value = ''
    }
    // 对于需要编码的文本（比如说中文）我们要进行编码
    params.push([key, encodeURIComponent(value)].join('='))
  })

  return params.join('&')
}

function encodeUrl(baseUrl, obj) {
  return `${baseUrl}?${encodeParams(obj)}`
}

/**
 * 0 nothing
 * 1 me following the user (userCode)
 * 2 the user (userCode) following me
 * 3 bi-follower
 * @param me
 * @param userCode
 */
function followship(me, userCode) {
  let retval = 0;
  try {
    if(me.following.indexOf(userCode) >= 0){
      if(me.follower.indexOf(userCode) >= 0) retval = 3;
      else retval = 1
    }
    else if(me.follower.indexOf(userCode) >= 0) retval = 2;
  } catch(error) {
  }
  return retval;
}

var blocked = (me, user) => {
  try {
    return (me.blacked.indexOf(user.userCode) >= 0)
  } catch(error) {
  }
  return false;
}

const imageFilter1 = function(req, file, cb) {
  // accept image only
  if(!file.originalname.match(/\.(jpg|jpeg|png|gif)$/)){
    return cb(new Error('Only image files are allowed!'), false);
  }
  cb(null, true);
};
const imageFilter2 = function(originalname) {
  // accept image only
  if(!originalname.match(/\.(jpg|jpeg|png|gif)$/)){
    return false;
  }
  return true;
};
const imageFilter = function(fileExt) {
  // accept image only
  let _ext = ['jpg', 'jpeg', 'png', 'gif']
  if(_ext.indexOf(fileExt.toLowerCase()) > -1){
    return true;
  }
  return false;
}

// make promise version of fs.readFile()
var fs = require('fs');
fs.readFileAsync = function(filename) {
  return new Promise(function(resolve, reject) {
    fs.readFile(filename, function(err, data) {
      if(err)
        reject(err);
      else
        resolve(data);
    });
  });
}

const readFile_promise = function(filename) {
  return fs.readFileAsync(filename)
}
/*
fs.readFileAsync = util.promisify(fs.readFile);
const readFileAsync = fs.readFileAsync(filename)
  .then(data=>{
    // console.log(data)
  })
*/

/*
const fsPromises = require('fs').promises

const func = async filenames => {

  for(let fn of filenames) {
    let data = await fsPromises.readFile(fn)
  }

}

func(['file1','file2'])
 */

function inList(list, value) {
  let retval = false;
  try {
    retval = (list.indexOf(value) > -1);
  } catch(e) {
  }
  return retval;
}

function userCodes(objList) {
  var userCodeList = [];
  objList.forEach(r => {
    userCodeList.push(r.userCode);
  });
  return userCodeList;
}

var getRecord = (modelName, fieldName, fieldValue) => new Promise((resolve, reject) => {
  var name = fieldName;
  var value = fieldValue;
  var query = {};
  query[name] = value;
  modelName.findOne(query, (err, item) => {
    if(err){
      reject({errorCode: 0, message: err.message});
    }
    else {
      if(!item){
        reject({
          errorCode: 0,
          message: `cannot find ${fieldName}: ${fieldValue} in collection: ${modelName.collection.collectionName}`
        });
      }
      else {
        // console.log(`found ${fieldName}: ${fieldValue} in collection: ${modelName.collection.collectionName}`);
        resolve(item);
      }
    }
  });
})

var saveRecord = (recordName, passData) => new Promise((resolve, reject) => {
  recordName.save((err) => {
    if(err){
      reject({errorCode: 0, message: err.message});
    }
    else {
      resolve(passData);
    }
  });
})

var getAllRecord_Fields
(modelName, fields) => new Promise((resolve => {
  modelName.find({}, fields).exec()
  then(items => {
    resolve(items)
  }).catch(err => {
    console.error(err)
  })
}))

var followship = (me, user) => {
  let retval = 0;
  try {
    if(me.following.indexOf(user.userCode) >= 0){
      if(me.follower.indexOf(user.userCode) >= 0) retval = 3;
      else retval = 1
    }
    else if(me.follower.indexOf(user.userCode) >= 0) retval = 2;
  } catch(error) {
  }
  return retval;
}

module.exports = {
  mobileValidate: (countryCode, mobile) => mobileValidate(countryCode, mobile),
  getRecord: (modelName, fieldName, fieldValue) => getRecord(modelName, fieldName, fieldValue),
  getAllRecord_Fields: (modelName, fields) => getAllRecord_Fields(modelName, fields),
  saveRecord: (recordName, passData) => saveRecord(recordName, passData),
  userCodes: (objList) => userCodes(objList),
  inList: (list, value) => inList(list, value),
  objCopy: (sourceObj, destObj) => objCopy(sourceObj, destObj),
  mockupMoment: mockupMoment,
  mockupUserMoment: (userCode) => mockupUserMoment(userCode),
  mockupUser: mockupUser,
  //imageFilter: (req,file,cb)=>imageFilter(req,file,cb),
  imageFilter: imageFilter,
  readFile_promise: readFile_promise,
  mockupVideo: mockupVideo,
  getToken: (seed) => getToken(seed),
  convertoUrl: (fileName, localdir) => convertoUrl(fileName, localdir),
  encodeUrl: (baseUrl, obj) => encodeUrl(baseUrl, obj),
  encodeParams: (obj) => encodeParams(obj),
  followship: (me, userCode) => followship(me, userCode),
  blocked: blocked,
  phoneFormalize: phoneFormalize
}

function convertoUrlTest() {
  console.log(convertoUrl('momentPhotos-1538731034345'))
  console.log(convertoUrl('momentPhotos-1538731034345', 'video'))
}

function encodeParamsTest() {
  /*---------------------
  本文来自 BenjaminShih 的CSDN 博客 ，全文地址请点击：https://blog.csdn.net/sjn0503/article/details/74936613?utm_source=copy */
  var baseUrl = 'www.google.com'
  var a = 1, b = 'request', c = true
  //method 1
  var finalUrl = baseUrl + '?a=' + a + '&b=' + b + '&c=' + c
  console.log(finalUrl)
  //method 2
  finalUrl = `${baseUrl}?a=${a}&b=${b}&c=${c}`
  console.log(finalUrl)
  const obj = {
    a: 1,
    b: 'request',
    c: true,
  }
  //method 3, using a method function
  finalUrl = `${baseUrl}?${encodeSearchParams(obj)}`
  console.log(finalUrl)
}
